iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0

TabLayout是 Android 中用來建立標籤式介面(分頁)的 UI 元件,通常和 ViewPager2 搭配使用,讓使用者可以在多個頁面之間滑動切換。

元件 說明
TabLayout 提供上方的分頁(tabs)按鈕。
ViewPager2 管理每個分頁要顯示的內容(Fragment)。
TabLayoutMediator 將 TabLayout 和 ViewPager2 綁定。

TabLayout 常用屬性說明

1. tabGravity

  • 用途:決定 TabItem 在 TabLayout 裡的排列方式。
  • 可用參數
    • center:所有 TabItem 會集中排列在 TabLayout 的中間。
    • fill:TabItem 會平均分配整個 TabLayout 的寬度。

2. tabIndicatorColor

  • 用途:設定下方指示線(indicator,即底線)的顏色。

3. tabIndicatorFullWidth

  • 用途:指示線是否填滿整個 TabItem 下方。
  • 參數
    • true:底線會完全填滿 TabItem 寬度。
    • false:底線會依據內容文字寬度顯示。

4. tabMaxWidth

  • 用途:限定每個 TabItem 的最大寬度(常用於橫向螢幕)。
  • 常見設定:0dp 代表可自動填滿。

5. tabMode

  • 用途:TabItem 太多時,決定如何顯示。
  • 可用參數
    • fixed:所有 TabItem 都塞進 TabLayout(預設),若空間不夠會壓縮每個 Tab。
    • scrollable:TabItem 太多時可以橫向滑動,多出來的 Tab 就用滑動檢視。

6. tabSelectedTextColor

  • 用途:被選取時 TabItem 文字的顏色。

7. tabTextColor

  • 用途:一般狀態下 TabItem 文字的顏色(未被選取時)。

8. tabBackground

  • 用途:設定 TabItem 的背景,可以用 drawable 資源。

9. tabIndicatorHeight

  • 用途:設定底線的高度,設為 0dp 就會隱藏底線。

範例程式碼:

首先要在build.gradle (Module app)中加入下列這一行:
implementation'com.google.android.material:material:1.11.0'


activity_main

版面配置,記得放入TabLayout和ViewPager2

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Monday" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tuesday" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Wednesday" />

    </com.google.android.material.tabs.TabLayout>

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

MainActivity


最上面記得加,否則會報錯

import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;

在MainActivity中宣告

private ViewPager2 viewPager;
private TabLayout tab;
private FragmentViewPagerAdapter adapter;

建立一個 FragmentViewPagerAdapter 實例,並將當前的 Activity(用 this 表示)傳入建構子

之後這個 adapter 會被用來設定給 ViewPager2,以實現分頁切換功能。
另外,ViewPager2 預設就是從第 0 頁開始,所以如果沒有特別需求,最後一行可以省略,此處寫出來只是為了告知可從這行設定。

adapter = new FragmentViewPagerAdapter(this);
viewPager.setAdapter(adapter);// 設定 ViewPager 的 adapter
viewPager.setCurrentItem(0);// 設定一開始顯示第0頁

Fragment:TabLayout(TabItem)有幾個就創幾個

因為我的有三個,所以創了FragmentA FragmentB和FragmentC

image

new TabLayoutMediator(tab, viewPager, new TabLayoutMediator.TabConfigurationStrategy() {
    @Override
    public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
        //Tab顯示的字
        if (position == 0) tab.setText("首頁");
        if (position == 1) tab.setText("最新消息");
        if (position == 2) tab.setText("介紹");
    }
}).attach();

點擊事件
ps.如要使用Toast請記得在最上方加入import android.widget.Toast;

tab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        //Tab被選中時 發出提示訊息
        Toast.makeText(MainActivity.this, tab.getText(), Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
        // Tab取消選中時
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {
        // Tab被再次選中時
    }
});

FragmentViewPagerAdapter


這頁是我們自訂的ViewPager2 的 Fragment 適配器,用來讓 App 可以滑動切換不同頁面,可以看程式碼內的備註了解每行意思

public class FragmentViewPagerAdapter extends FragmentStateAdapter {
    //初始化
    public FragmentViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        //0表示最左邊的Tab 當我們滑動或點擊時就會顯示FragmentA
        if (position == 0){
            return new FragmentA();
        }
        //中間/第二個Tab
        else if (position == 1){
            return new FragmentB();
        }
        else {
            //最後一個 因為只有3個所以直接寫else就好了
            return new FragmentC();
        }
    }

    @Override
    //代表這個 ViewPager 一共有 3 頁(對應 3 個 Fragment)。
    public int getItemCount() {
        return 3;
    }
}

FragmentA


每頁自然是可以單獨做版面設計,但是用到的語法可能會不太一樣,像我的是單獨放一張圖片作展示

Fragment 必須要有一個公開無參數的建構子,否則系統在重建 Fragment 時會報錯

public class FragmentA extends Fragment {

    public FragmentA() {
        // 必須的空建構子
    }

    private ImageView imageView;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {

        // 膨脹 fragment 的佈局檔,並存成 view
        //R.layout.activity_fragmenta 是這個 Fragment 使用的 XML 佈局。
        //用 inflater 把 XML 轉成 Java 中的 View 物件。
        View view = inflater.inflate(R.layout.activity_fragmenta, container, false);

        // 用 view.findViewById() 找出元件
        imageView = view.findViewById(R.id.imageView);

        // 回傳 view
        return view;
    }
}

成果展示:
image alt


什麼是「膨脹」(Inflate)?

在 Android 中,我們設計畫面通常會先寫好 XML 檔,但這只是一段靜態的 XML 檔,還不是程式中可操作的畫面元件。
當你在程式中執行這段:

View view = inflater.inflate(R.layout.activity_fragmenta, container, false);

就代表你在把 XML 畫面檔「膨脹」(inflate)成 Java 中可以操作的 View 物件。也就是把activity_fragmenta.xml → 轉換 → View 物件(Java 裡可以 .findViewById() 的)

而在綁定元件時必須寫成view.findViewById(R.id.imageView),也就是要在前面多加一個view. ,其他的都跟平時寫程式沒有差別,寫完後記得要return view,不然畫面不會顯示喔


上一篇
Day 20.SharedPreferences
下一篇
Day 22.Retrofit
系列文
Android 新手的 30 天進化論:從初學者到小專案開發者22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言